package me.fangsong.timefold.line.domain;

import ai.timefold.solver.core.api.domain.entity.PlanningEntity;
import ai.timefold.solver.core.api.domain.lookup.PlanningId;
import ai.timefold.solver.core.api.domain.variable.CascadingUpdateShadowVariable;
import ai.timefold.solver.core.api.domain.variable.InverseRelationShadowVariable;
import ai.timefold.solver.core.api.domain.variable.NextElementShadowVariable;
import ai.timefold.solver.core.api.domain.variable.PreviousElementShadowVariable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.LocalTime;
import java.time.temporal.ChronoUnit;

@PlanningEntity
public class Work {
    private static final Logger logger = LoggerFactory.getLogger(Work.class);
    @PlanningId
    private Integer id;
    private String workName;
    private Integer workMinute;

    @InverseRelationShadowVariable(sourceVariableName = "workList")
    private Line line;
    @PreviousElementShadowVariable(sourceVariableName = "workList")
    private Work previousWork;
    @NextElementShadowVariable(sourceVariableName = "workList")
    private Work nextWork;

    @CascadingUpdateShadowVariable(targetMethodName = "updateStartTime")
    private LocalTime startTime;

    //@CascadingUpdateShadowVariable(targetMethodName = "updateEndTime")
    private LocalTime endTime;

    public Work() {
    }

    public Work(Integer id, String workName , Integer workMinute) {
        this.workMinute = workMinute;
        this.workName = workName;
        this.id = id;
    }

    public String getWorkName() {
        return workName;
    }

    public void setWorkName(String workName) {
        this.workName = workName;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getWorkMinute() {
        return workMinute;
    }

    public void setWorkMinute(Integer workMinute) {
        this.workMinute = workMinute;
    }

    public Line getLine() {
        return line;
    }

    public void setLine(Line line) {
        this.line = line;
    }

    public Work getPreviousWork() {
        return previousWork;
    }

    public void setPreviousWork(Work previousWork) {
        this.previousWork = previousWork;
    }

    public Work getNextWork() {
        return nextWork;
    }

    public void setNextWork(Work nextWork) {
        this.nextWork = nextWork;
    }

    public LocalTime getStartTime() {
        return startTime;
    }

    public void setStartTime(LocalTime startTime) {
        this.startTime = startTime;
    }

    public LocalTime getEndTime() {
        return endTime;
    }

    public void setEndTime(LocalTime endTime) {
        this.endTime = endTime;
    }

    public void updateStartTime() {
        if(line==null){
            return;
        }
        if(previousWork == null) {
            startTime = line.getMorningStartTime();
        }
        else {
            startTime = previousWork.getEndTime();
        }
        updateEndTime();
    }

    public void updateEndTime() {
        if(line==null||startTime==null) {
            return;
        }
        if(startTime.isBefore(line.getMorningEndTime())) {
            LocalTime workEndTime = startTime.plusMinutes(workMinute);
            if(workEndTime.isBefore(line.getMorningEndTime())||workEndTime.equals(line.getMorningEndTime())) {
                endTime = workEndTime;
            }
            else if(workEndTime.isAfter(line.getMorningEndTime())&&workEndTime.isBefore(line.getAfternoonEndTime())) {
                Long leftTime = workMinute - Math.abs((ChronoUnit.MINUTES.between(startTime,line.getMorningEndTime())));
                endTime = line.getAfternoonStartTime().plusMinutes(leftTime);
            }
        }
        else if(startTime.isAfter(line.getAfternoonStartTime())){
            endTime = startTime.plusMinutes(workMinute);
         }
    }
}
